﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Ex03.GarageLogic
{
    public class Garage
    {
        private VehicleInGarageCollection m_VehicleInGarageCollection;

        public Garage()
        {
            m_VehicleInGarageCollection = new VehicleInGarageCollection();
        }

        /// <summary>
        /// Adds a vehicle to the garage.
        /// If the vehicle already exists, changes its status to Repairing.
        /// </summary>
        /// <param name="i_Vehicle">The vehicle to add.</param>
        /// <param name="i_VehicleOwner">The owner of the vehicle to add to the garage.</param>
        /// <returns>True if the vehicle already exists in the garage. False otherwise.</returns>
        public bool AddVehicle(Vehicle i_Vehicle, VehicleOwner i_VehicleOwner)
        {
            bool alreadyExists = false;

            if (m_VehicleInGarageCollection.VehicleExists(i_Vehicle))
            {
                alreadyExists = true;
                VehicleInGarage vehicleInGarage =
                    m_VehicleInGarageCollection.GetVehicleByLicensingNumber(i_Vehicle.LicensingNumber);
                vehicleInGarage.VehicleStatus = eVehicleStatus.Repairing;
            }
            else
            {
                m_VehicleInGarageCollection.AddVehicle(i_Vehicle, i_VehicleOwner);
            }

            return alreadyExists;
        }

        /// <summary>
        /// Returns all the vehicles in the garage.
        /// </summary>
        /// <returns>All the vehicles in the garage.</returns>
        public List<Vehicle> GetAllVehicles()
        {
            List<Vehicle> vehicleList = new List<Vehicle>();
            List<VehicleInGarage> vehicleInGarageList =
                m_VehicleInGarageCollection.GetAllVehicles();

            foreach (VehicleInGarage vehicleInGarage in vehicleInGarageList)
            {
                vehicleList.Add(vehicleInGarage.Vehicle);
            }

            return vehicleList;
        }

        /// <summary>
        /// Returns all the vehicles that have the given status in the garage.
        /// </summary>
        /// <param name="i_VehicleStatus">The vehicle status to filter by.</param>
        /// <returns>All the vehicles filtered by the given vehicle status.</returns>
        public List<Vehicle> GetVehiclesByVehicleStatus(eVehicleStatus i_VehicleStatus)
        {
            List<Vehicle> vehicleList = new List<Vehicle>();
            List<VehicleInGarage> vehicleInGarageList = 
                m_VehicleInGarageCollection.GetVehiclesByVehicleStatus(i_VehicleStatus);

            foreach (VehicleInGarage vehicleInGarage in vehicleInGarageList)
            {
                vehicleList.Add(vehicleInGarage.Vehicle);
            }

            return vehicleList;
        }

        /// <summary>
        /// Sets the status of the vehicle in the garage.
        /// </summary>
        /// <param name="i_LicensingNumber">The licensing number of the vehicle to change the status to.</param>
        /// <param name="i_VehicleStatus">The new status of the car.</param>
        public void SetVehicleStatus(string i_LicensingNumber, eVehicleStatus i_VehicleStatus)
        {
            VehicleInGarage vehicleInGarage = m_VehicleInGarageCollection.GetVehicleByLicensingNumber(i_LicensingNumber);
            vehicleInGarage.VehicleStatus = i_VehicleStatus;
        }

        /// <summary>
        /// Inflates all the wheels of the vehicle to their maximal air pressure.
        /// </summary>
        /// <param name="i_LicensingNumber">The licensing number of the vehicle to inflate the wheels to.</param>
        public void InflateWheelsToMaximum(string i_LicensingNumber)
        {
            VehicleInGarage vehicleInGarage = m_VehicleInGarageCollection.GetVehicleByLicensingNumber(i_LicensingNumber);
            vehicleInGarage.Vehicle.InflateWheelsToMaximum();
        }

        /// <summary>
        /// Refuels a fuel vehicle.
        /// </summary>
        /// <param name="i_LicensingNumber">The licensing number of the vehicle to refuel.</param>
        /// <param name="i_FuelLitresToAdd">The amount of litres of fuel to add.</param>
        /// <param name="i_FuelTypeToAdd">The type of fuel to add.</param>
        public void Refuel(string i_LicensingNumber, float i_FuelLitresToAdd, eFuelType i_FuelTypeToAdd)
        {
            VehicleInGarage vehicleInGarage = m_VehicleInGarageCollection.GetVehicleByLicensingNumber(i_LicensingNumber);
            FuelVehicle fuelVehicle = vehicleInGarage.Vehicle as FuelVehicle;

            if (fuelVehicle == null)
            {
                throw new ArgumentException("The vehicle is not a fuel vehicle.");
            }

            if (fuelVehicle.FuelType != i_FuelTypeToAdd)
            {
                throw new ArgumentException("Wrong fuel type.");
            }

            fuelVehicle.Refuel(i_FuelLitresToAdd, i_FuelTypeToAdd);
        }

        /// <summary>
        /// Charges the battery of a given vehicle.
        /// </summary>
        /// <param name="i_LicensingNumber">Thje licensing number of the vehicle to charge.</param>
        /// <param name="i_BatteryHoursToAdd">The number of hours to add to the battery charge.</param>
        public void ChargeBattery(string i_LicensingNumber, float i_BatteryHoursToAdd)
        {
            VehicleInGarage vehicleInGarage = m_VehicleInGarageCollection.GetVehicleByLicensingNumber(i_LicensingNumber);
            ElectricVehicle electricVehicle = vehicleInGarage.Vehicle as ElectricVehicle;

            if (electricVehicle == null)
            {
                throw new ArgumentException("The vehicle is not an electric vehicle.");
            }

            electricVehicle.ChargeBattery(i_BatteryHoursToAdd);
        }

        /// <summary>
        /// Returns a vehicle that has the given licensing number.
        /// </summary>
        /// <param name="i_LicensingNumber">The licensing number of the vehicle.</param>
        /// <returns>The vehicle that has the given licensing number.</returns>
        public VehicleInGarage GetVehicleInGarageByLicensingNumber(string i_LicensingNumber)
        {
            return m_VehicleInGarageCollection.GetVehicleByLicensingNumber(i_LicensingNumber);
        }
    }
}